/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package custom.log4j;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.Level;
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

/**
 *
 * @author david
 */
public class JTextPaneAppender extends AppenderSkeleton {

    private JTextPane textPane = null;
    private static final int TRACE_IDX = 0;
    private static final int DEBUG_IDX = 1;
    private static final int INFO_IDX = 2;
    private static final int WARN_IDX = 3;
    private static final int ERROR_IDX = 4;
    private static final int FATAL_IDX = 5;
    private Style[] styles = new Style[FATAL_IDX + 1];
    private Style defaultStyle = null;

    public JTextPaneAppender() {
    }

    public JTextPaneAppender(final JTextPane textPane) {
        setTextPane(textPane);
    }

    public void setTextPane(final JTextPane textPane) {
        this.textPane = textPane;

        // See if user put any styles specific to a level.

        Style style;
        // If there is a style called All, it is intended to be used for all levels.
        if ((style = textPane.getStyle("All")) != null) {
            for (int i = 0; i < FATAL_IDX + 1; i++) {
                styles[i] = style;
            }
        } else if ((style = textPane.getStyle("Trace")) != null) {
            styles[TRACE_IDX] = style;
        } else if ((style = textPane.getStyle("Debug")) != null) {
            styles[DEBUG_IDX] = style;
        } else if ((style = textPane.getStyle("Info")) != null) {
            styles[INFO_IDX] = style;
        } else if ((style = textPane.getStyle("Warn")) != null) {
            styles[WARN_IDX] = style;
        } else if ((style = textPane.getStyle("Error")) != null) {
            styles[ERROR_IDX] = style;
        } else if ((style = textPane.getStyle("Fatal")) != null) {
            styles[FATAL_IDX] = style;
        }

        // Any syles that are null will be set to the defaultStyle.
        initDefaultStyle();
        for (int i = 0; i < FATAL_IDX + 1; i++) {
            if (styles[i] == null) {
                styles[i] = defaultStyle;
            }
        }
    }

    public JTextPane getTextPane() {
        return textPane;
    }

    private void initDefaultStyle() {
        defaultStyle = textPane.addStyle("Default", null);
        StyleConstants.setFontFamily(defaultStyle, "Courier");
        StyleConstants.setBackground(defaultStyle, Color.white);
        StyleConstants.setForeground(defaultStyle, Color.black);
    }

    protected void append(LoggingEvent le) {
        String logMsg = this.layout != null ? this.layout.format(le) : (String) le.getMessage();

        if (textPane != null) {
            Style s = defaultStyle;
            if (le.getLevel() == Level.TRACE) {
                s = styles[TRACE_IDX];
            } else if (le.getLevel() == Level.DEBUG) {
                s = styles[DEBUG_IDX];
            } else if (le.getLevel() == Level.INFO) {
                s = styles[INFO_IDX];
            } else if (le.getLevel() == Level.WARN) {
                s = styles[WARN_IDX];
            } else if (le.getLevel() == Level.ERROR) {
                s = styles[ERROR_IDX];
            } else if (le.getLevel() == Level.FATAL) {
                s = styles[FATAL_IDX];
            }

            Document doc = textPane.getStyledDocument();

            try {
                doc.insertString(doc.getLength(), logMsg, s);

                if (this.layout != null && this.layout.ignoresThrowable()) {
                    String[] lines = le.getThrowableStrRep();
                    if (lines != null) {
                        for (String line : lines) {
                            doc.insertString(doc.getLength(), line, s);
                        }
                    }
                }
            } catch (BadLocationException e) {

            }

            textPane.setCaretPosition(doc.getLength());
        }
    }

    public boolean requiresLayout() {
        return true;
    }

    public void close() {
    }
}
